package com.acwer.framework.data;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;

import com.acwer.framework.common.FuncTwo;




public class TreeUtil {
	
	/**
	 * 父子节点
	 * @param list 要生成的列表
	 * @param pkFunc 获取主键
	 * @param fkFun  获取外键
	 * @return
	 */
	public static<T> TreeList<TreeNode<T>> generTreeByParent(
			TreeNode<T> parentNode,
			List<? extends T>list,
			FuncTwo<T, String> pkFunc,
			FuncTwo<T, String> fkFun){
		
		//String parentId=null;
		String id=null;
		//1.获取主键
		if(parentNode!=null&&pkFunc.accept(parentNode.getNode())!=null) id=pkFunc.accept(parentNode.getNode());
		if(StringUtils.isEmpty(id)) id="";
		String pkId=id;
		
		TreeList<TreeNode<T>> treeList=new TreeList<TreeNode<T>>();
		
		
		Predicate<T> filter=(it)->pkId.equals(fkFun.accept(it));
		
		if(pkId.length()==0) filter=(it)->StringUtils.isEmpty(fkFun.accept(it));
		
		List<T> ls=list.stream().filter(filter).collect(Collectors.toList());
		
		for (T node : ls) {
			TreeNode<T> treeNode=new TreeNode<T>();
			treeNode.setNode(node);
			//设置父节点
			if(parentNode!=null){
				TreeNode<T> p=new TreeNode<T>();
				p.setNode(parentNode.getNode());
				treeNode.setParentNode(p);
			}
			treeNode.setChildren(generTreeByParent(treeNode, list,pkFunc,fkFun));
			treeList.add(treeNode);
		}
		if(ls.size()==0) return null;
		
		return treeList;
	}
	public static<T> TreeList<TreeNode<T>> generTreeList(TreeNode<T> parentNode,
			List<? extends T>list,
			FuncTwo<T, String> thunk,
			int step){
		
		return generTreeListV2(parentNode, list, thunk, new ArrayList<Integer>(){
			{
				add(step);
			}
		}, 0);
	}
	
	/**
	 * 没能生成的数节点添加进去
	 * @param parentNode
	 * @param list
	 * @param thunk
	 * @param steps
	 * @param start
	 * @return
	 */
	public static<T> TreeList<TreeNode<T>> generTreeFullList(TreeNode<T> parentNode,
			List<? extends T>list,
			FuncTwo<T, String> thunk,
			List<Integer>steps,
			int start){
		
		TreeList<TreeNode<T>> treeList=generTreeListV2(parentNode, list, thunk, steps, start);
		List<String> subKeys=getSubOfList(treeList, thunk);
		int indx=0;
		for (T it : list) {
			String key=thunk.accept(it);
			if(!subKeys.contains(key)){
				TreeNode<T> treeNode=new TreeNode<T>();
				treeNode.setNode(it);
				treeList.add(indx++, treeNode);
			}
		}
		return treeList;
	}
	/**
	 * 获取tree里面的的部分属性
	 * @param treeList
	 * @param thunk
	 * @return
	 */
	public static<T> List<String> getSubOfList(TreeList<TreeNode<T>> treeList,FuncTwo<T,String>thunk) {
		List<String> ls=new ArrayList<String>();
		for (TreeNode<T> node : treeList) {
			ls.add(thunk.accept(node.getNode()));
			ls.addAll(getSubOfList(node.getChildren(), thunk));
		}
		return ls;
	}
	/**
	 * �������νṹ
	 * @param plevel �ϼ�Level
	 * @param list ����Դ
	 * @param thunk ���ɲ���
	 * @param step �ָ��ַ���
	 * @return TreeList<T>
	 */
	public static<T> TreeList<TreeNode<T>> generTreeListV2(TreeNode<T> parentNode,
			List<? extends T>list,
			FuncTwo<T, String> thunk,
			List<Integer>steps,
			int start){
		
		TreeList<TreeNode<T>> treeList=new TreeList<TreeNode<T>>();
		String lev=parentNode==null?"":thunk.accept(parentNode.getNode());
		
		int step=0;
		if(steps.size()<=start) step=steps.get(steps.size()-1);
		else step=steps.get(start);
		
		int takeSize=lev.length()+step;
		
		//过滤条件
		Predicate<T> filter=(it)->thunk.accept(it).length()==takeSize &&thunk.accept(it).startsWith(lev);
		if(lev.length()==0)
			filter=it->thunk.accept(it).length()==takeSize;
			
		List<T>ls=list.stream().filter(filter).collect(Collectors.toList());
		//排序
		ls.sort((a,b)->thunk.accept(a).compareTo(thunk.accept(b)));
		
		for (T node : ls) {
			
			TreeNode<T> treeNode=new TreeNode<T>();
			treeNode.setNode(node);
			treeNode.setParentNode(parentNode);
			treeNode.setChildren(generTreeListV2(treeNode, list, thunk,steps, ++step));
			
			treeList.add(treeNode);
		}
		if(ls.size()==0) return null;
		
		return treeList;
	}
	/**
	 * 去掉首尾字符及去重
	 * @param str
	 * @param element
	 * @return
	 */
	public static String trimFirstAndLastChar(String str, String element){
		
	    if(StringUtils.isEmpty(element)) return str;
	    List<String> strLs=Arrays.asList(str.split(element));
	    strLs=strLs.stream().filter(it->StringUtils.isNotEmpty(it)&&!it.equals(element)).collect(Collectors.toList());
	   
	    return String.join(element, strLs);
	}
	
}
